﻿using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Driver;

namespace Murry.DataStore.MongoDB
{
    /// <summary>
    /// MongoDB implementation of a DataStore.
    /// </summary>
    public class MongoDataStore : DataStore<MongoDatabase>
    {
        /// <summary>
        /// Create new DataStore.
        /// </summary>
        /// <param name="connectionString">Connection String.</param>
        /// <param name="databaseName">Database Name.</param>
        public MongoDataStore(string connectionString, string databaseName)
        {
            var client = new MongoClient(connectionString);
            Database = client.GetServer().GetDatabase(databaseName);
        }

        /// <summary>
        /// Get IQueryable interface for a given type.
        /// </summary>
        /// <typeparam name="TInterface">Type.</typeparam>
        /// <returns>Queryable interface.</returns>
        public override IEnumerable<TInterface> FindAll<TInterface>() 
        {
            var implementedType = Entities.GetImplementedEntityType(GetType(), typeof(TInterface));
            var collection = Database.GetCollection(implementedType, implementedType.Name);
            var e = collection.FindAllAs<TInterface>();
            return e;
        }

        /// <summary>
        /// Find an object by ID.
        /// </summary>
        /// <typeparam name="TInterface">Type of object to find.</typeparam>
        /// <param name="id">Object ID.</param>
        /// <returns>The found object.</returns>
        public override TInterface FindById<TInterface>(string id) 
        {
            var implementedType = Entities.GetImplementedEntityType(GetType(), typeof(TInterface));
            var collection = Database.GetCollection(implementedType, implementedType.Name);
            var o = collection.FindOneByIdAs(implementedType, ObjectId.Parse(id));

            return (TInterface)o;
        }

        /// <summary>
        /// Helper method to register entities.
        /// </summary>
        /// <param name="interfaceType">Interface type.</param>
        /// <param name="implementationType">Implemented type.</param>
        public static void RegisterEntity(Type interfaceType, Type implementationType)
        {
            Entities.AddEntity(typeof(MongoDataStore), interfaceType, implementationType);
        }
    }
}
